﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using System.ComponentModel.DataAnnotations;
using GoodStuff.Validation;

namespace GoodStuff.UnitTests
{
    [TestFixture]
    public class TestValidators
    {       
        [Test]
        public void ValidateSimple()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();            
            var results = Validation.Validator.Validate(newDemo);
            
            Assert.IsFalse(results.IsValid);
            Assert.IsTrue(results.Errors.Count() > 0);
        }

        [Test]
        public void SyntaxSample()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();

            IValidationRule<string> rule = new Validation.Rules.IsRequiredRule();
            rule.Validate("hello");
            Assert.IsTrue(rule.IsValid);
        }


        [Test]
        public void TestCompoundValidator()
        {
            IValidationRule<string> rule = new Validation.Rules.IsRequiredRule();
            IValidationRule<string> rule2 = new Validation.Rules.StringLengthRule(20);
            var rules = new List<IValidationRule<string>>() { rule, rule2 };

            IValidationRule<string> compound = new Validation.Rules.CompoundValidator<string>(rules);
            compound.Validate("hello");
            Assert.IsTrue(compound.IsValid);
        }


        [Test]
        public void TestCompoundPropertyValidator()
        {
            IValidationRule<string> rule = new Validation.Rules.IsRequiredRule();
            IValidationRule<string> rule2 = new Validation.Rules.StringLengthRule(20);
            var rules = new List<IValidationRule<string>>() { rule, rule2 };

            var compound = new Validation.Rules.PropertyValidator<DemoBusinessClass,string>(p => p.Email, rules);
            compound.Validate(new DemoBusinessClass() { Email = "valid" });
            Assert.IsTrue(compound.IsValid);
        }

        [Test]
        public void TestCompoundValidatorFails()
        {
            IValidationRule<string> rule = new Validation.Rules.IsRequiredRule();
            IValidationRule<string> rule2 = new Validation.Rules.StringLengthRule(20);
            var rules = new List<IValidationRule<string>>() { rule, rule2 };

            IValidationRule<string> compound = new Validation.Rules.CompoundValidator<string>(rules);
            compound.Validate("oiewuroiew roiew roiew urew uroiu ooi uoiuooiewur oiew uroiew oi");
            Assert.IsFalse(compound.IsValid);
        }

        [Test]
        public void TestCompoundValidatorFailsEmpty()
        {
            IValidationRule<string> rule = new Validation.Rules.IsRequiredRule();
            IValidationRule<string> rule2 = new Validation.Rules.StringLengthRule(20);
            var rules = new List<IValidationRule<string>>() { rule, rule2 };

            IValidationRule<string> compound = new Validation.Rules.CompoundValidator<string>(rules);
            compound.Validate(null);
            Assert.IsFalse(compound.IsValid);
        }

        [Test]
        public void SyntaxSample2()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();
            newDemo.Email = "emailaddress";

            IValidationRule<DemoBusinessClass> rule = new Validation.Rules.PropertyValidator<DemoBusinessClass, string>(p => p.Email, new Validation.Rules.IsRequiredRule());
            rule.Validate(newDemo);
            Assert.IsTrue(rule.IsValid);
        }


        [Test]
        public void EntityValidatorSample()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();
            newDemo.Email = "emailaddress";

            IRuleBuilder<DemoBusinessClass> validator = new DemoBusinessValidator();
            var results = validator.Validate(newDemo);
            Assert.IsTrue(results.IsValid);
        }

        [Test]
        public void EntityValidatorSampleFails()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();
            newDemo.Email = "";

            IRuleBuilder<DemoBusinessClass> validator = new DemoBusinessValidator();
            var results = validator.Validate(newDemo);
            Assert.IsFalse(results.IsValid);
        }

        [Test]
        public void EntityValidatorSampleFailsTooLong()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass();
            newDemo.Email = "oiufrew oiewuroiew uroiew roiew urewuroiew uroiewuroiew u";

            IRuleBuilder<DemoBusinessClass> validator = new DemoBusinessValidator();
            var results = validator.Validate(newDemo);
            Assert.IsFalse(results.IsValid);
        }

        [Test]
        public void ValidateSimpleOK()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke dirk", Email = "test@test.com" };
            DemoBusinessValidator rules = new DemoBusinessValidator();
            var results = Validator.Validate(rules, newDemo);

            Assert.IsTrue(results.IsValid);
        }

        [Test]
        public void ValidateSimpleEmpty()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "" };
            DemoBusinessValidator rules = new DemoBusinessValidator();
            var results = Validator.Validate(rules, newDemo);

            Assert.IsFalse(results.IsValid);
        }

        [Test]
        public void ValidateSimpleTooLong()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke dirk viel van de kerktoren" };
            DemoBusinessValidator rules = new DemoBusinessValidator();

            var results = Validator.Validate(rules, newDemo);

            Assert.IsFalse(results.IsValid);
        }

        [Test]
        public void ValidateAssertion()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke dirk", Password = "abc", Email = "valid@valid.com" };
            DemoBusinessValidator rules = new DemoBusinessValidator();

            rules.Assert(newDemo);
        }

        [Test]
        public void ValidateExpressionFails()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke", Password = "1234" };
            DemoBusinessValidator rules = new DemoBusinessValidator();
            var results = Validator.Validate(rules, newDemo);

            Assert.IsFalse(results.IsValid);
        }

        [Test]
        [ExpectedException(typeof(GoodStuff.Validation.ValidationException))]
        public void ValidateAssertThrows()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke", Password = "1234" };
            DemoBusinessValidator rules = new DemoBusinessValidator();

            Validator.Assert(rules, newDemo);
        }

        [Test]
        public void ValidateExpressionGood()
        {
            DemoBusinessClass newDemo = new DemoBusinessClass() { UserName = "Dikke", Password = "abcde", Email = "valid@valid.org" };
            DemoBusinessValidator rules = new DemoBusinessValidator();
            var results = Validator.Validate(rules, newDemo);

            Assert.IsTrue(results.IsValid);
        }

        //[Test]
        //public void ValidateCustom()
        //{
        //    DemoBusinessClass newDemo = new DemoBusinessClass() { Password = "3b18rTje?XX" };
        //    DemoBusinessValidatorCustom rules = new DemoBusinessValidatorCustom();
        //    Validation.Assert(rules, newDemo);
        //}

        //[Test]
        //public void ValidateCustomFails()
        //{
        //    DemoBusinessClass newDemo = new DemoBusinessClass() { Password = "abcde" };
        //    DemoBusinessValidatorCustom rules = new DemoBusinessValidatorCustom();
        //    var results = Validation.Validate(rules, newDemo);

        //    Assert.IsFalse(results.IsValid);
        //}

        //[Test]
        //[ExpectedException(typeof(ArgumentException), ExpectedMessage = "Cannot verify", MatchType = MessageMatch.StartsWith)]
        //public void SetupFails()
        //{
        //    ImpossibleValidator rules = new ImpossibleValidator();
        //}

        public class DemoBusinessClass
        {
            [Required]
            public string UserName { get; set; }

            [Required(ErrorMessage="verplicht")]
            public string Password { get; set; }
            public bool HasEmail { get; set; }

            [Required]
            [StringLength(20)]
            public string Email { get; set; }
        }

        public class DemoBusinessValidator : EntityValidator<DemoBusinessClass>
        {
            protected override void Setup()
            {
                Require(x => x.Email, new Validation.Rules.IsRequiredRule());
                Require(x => x.Email, new Validation.Rules.StringLengthRule(20));
                //Require(x => x.HasEmail, new Validation.Rules.IsRequiredRule());
            }
        }

        //public class DemoBusinessValidatorCustom : BaseValidator<DemoBusinessClass>
        //{
        //    protected override void Setup()
        //    {
        //       Verify(p => p.Password).Validates(c => GoodStuff.Security.SecurePassword.IsStrong(c));
        //    }
        //}

        //public class ImpossibleValidator : BaseValidator<DemoBusinessClass>
        //{
        //    protected override void Setup()
        //    {
        //        Verify(p => p.UserName[4]).IsRequired();
        //    }
        //}
    }
}
